package xyz.apiote.bimba.czwek.dashboard

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.core.view.WindowCompat
import androidx.core.view.get
import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.openlocationcode.OpenLocationCode
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.dashboard.ui.home.HomeFragment
import xyz.apiote.bimba.czwek.dashboard.ui.map.MapFragment
import xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment
import xyz.apiote.bimba.czwek.databinding.ActivityMainBinding
import xyz.apiote.bimba.czwek.search.ResultsActivity
import xyz.apiote.bimba.czwek.settings.ServerChooserActivity
import xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity


class MainActivity : AppCompatActivity() {
	private lateinit var binding: ActivityMainBinding
	private lateinit var locationPermissionRequest: ActivityResultLauncher<Array<String>>

	private lateinit var permissionAsker: Fragment
	var locationPermissionDialogShown = false

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		binding = ActivityMainBinding.inflate(layoutInflater)
		setContentView(binding.root)

		getSharedPreferences("shp", MODE_PRIVATE).edit(true) {
			putBoolean("firstRun", false)
		}

		supportFragmentManager.registerFragmentLifecycleCallbacks(
			object : FragmentLifecycleCallbacks() {
				override fun onFragmentViewCreated(
					fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?
				) {
					setNavbarIcons(f)
					super.onFragmentViewCreated(fm, f, v, savedInstanceState)
				}
			}, true
		)

		val onBackPressedCallback =
			object : OnBackPressedCallback(binding.container.isDrawerOpen(binding.navigationDrawer)) {
				override fun handleOnBackPressed() {
					binding.container.closeDrawer(binding.navigationDrawer)
				}
			}
		onBackPressedDispatcher.addCallback(onBackPressedCallback)

		binding.container.addDrawerListener(object : DrawerListener {
			override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}

			override fun onDrawerOpened(drawerView: View) {
				onBackPressedCallback.isEnabled = true
			}

			override fun onDrawerClosed(drawerView: View) {
				onBackPressedCallback.isEnabled = false
			}

			override fun onDrawerStateChanged(newState: Int) {}
		})

		binding.navigationDrawer.setNavigationItemSelectedListener {
			when (it.itemId) {
				R.id.drawer_servers -> {
					startActivity(Intent(this, ServerChooserActivity::class.java))
				}

				R.id.drawer_cities -> {
					startActivity(Intent(this, FeedChooserActivity::class.java))
				}
			}
			false
		}

		WindowCompat.setDecorFitsSystemWindows(window, false)
		val navView: BottomNavigationView = binding.bottomNavigation
		val navHostFragment =
			supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment
		val navController = navHostFragment.navController
		navView.setupWithNavController(navController)

		locationPermissionRequest = registerForActivityResult(
			ActivityResultContracts.RequestMultiplePermissions()
		) { permissions ->
			when {
				permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false ||
								permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false -> {
					when (permissionAsker) {
						is HomeFragment -> {
							showResults(ResultsActivity.Mode.MODE_LOCATION)
						}

						is MapFragment -> {
							(permissionAsker as MapFragment).showLocation()
						}
					}
				}

				else -> {
					if (locationPermissionDialogShown) {
						return@registerForActivityResult
					}
					MaterialAlertDialogBuilder(this).setIcon(AppCompatResources.getDrawable(this, R.drawable.error_gps))
						.setTitle(getString(R.string.no_location_access))
						.setMessage(getString(R.string.no_location_message))
						.setPositiveButton(resources.getString(R.string.ok)) { _, _ ->}
						.show()
					locationPermissionDialogShown = true
				}
			}
		}
	}

	fun onNavigationClicked() {
		if (binding.container.isDrawerOpen(binding.navigationDrawer)) {
			binding.container.closeDrawer(binding.navigationDrawer)
		} else {
			binding.container.openDrawer(binding.navigationDrawer)
		}
	}

	fun onGpsClicked(fragment: Fragment) {
		when (PackageManager.PERMISSION_GRANTED) {
			ContextCompat.checkSelfPermission(
				this,
				Manifest.permission.ACCESS_COARSE_LOCATION
			) -> {
				when (fragment) {
					is HomeFragment -> {
						showResults(ResultsActivity.Mode.MODE_LOCATION)
					}

					is MapFragment -> {
						fragment.showLocation()
					}
				}
			}

			else -> {
				permissionAsker = fragment
				locationPermissionRequest.launch(
					arrayOf(
						Manifest.permission.ACCESS_FINE_LOCATION,
						Manifest.permission.ACCESS_COARSE_LOCATION
					)
				)
			}
		}
	}

	fun onSearchClicked(text: CharSequence?) {
		if (OpenLocationCode.isValidCode(text.toString())) {
			val olc = OpenLocationCode(text.toString())
			if (!olc.isFull) {
				Toast.makeText(this, getString(R.string.code_is_not_full), Toast.LENGTH_LONG).show()
				return
			}
			val area = olc.decode()
			showResults(olc.code, area.centerLatitude, area.centerLongitude)
		} else {
			showResults(ResultsActivity.Mode.MODE_SEARCH, text.toString())
		}
	}

	private fun showResults(query: String, centerLatitude: Double, centerLongitude: Double) {
		/* todo [3.2] (ux,low) animation
			https://developer.android.com/guide/fragments/animate
			https://github.com/raheemadamboev/fab-explosion-animation-app
		*/
		val intent = Intent(this, ResultsActivity::class.java).apply {
			putExtra("mode", ResultsActivity.Mode.MODE_POSITION)
			putExtra("query", query)
			putExtra("lat", centerLatitude)
			putExtra("lon", centerLongitude)
		}
		startActivity(intent)
	}

	private fun showResults(mode: ResultsActivity.Mode, query: String = "") {
		/* todo [3.2] (ux,low) animation
			https://developer.android.com/guide/fragments/animate
			https://github.com/raheemadamboev/fab-explosion-animation-app
		*/
		val intent = Intent(this, ResultsActivity::class.java).apply {
			putExtra("mode", mode)
			putExtra("query", query)
		}
		startActivity(intent)
	}

	private fun setNavbarIcons(f: Fragment) {
		// todo [voyage-planning]
		// binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_outline)
		binding.bottomNavigation.menu[1].setIcon(R.drawable.home_outline)
		binding.bottomNavigation.menu[0].setIcon(R.drawable.map_outline)
		when (f) {
			is HomeFragment -> {
				binding.bottomNavigation.menu[1].setIcon(R.drawable.home_black)
			}

			is VoyageFragment -> {
				binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_black)
			}

			is MapFragment -> {
				binding.bottomNavigation.menu[0].setIcon(R.drawable.map_black)
			}

			else -> {
				binding.bottomNavigation.menu[1].setIcon(R.drawable.home_black)
			}
		}
	}
}